package com.snail.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.snail.dto.LikeDTO;
import com.snail.mapper.BizCourseVideoLikeMapper;
import com.snail.model.pojo.study.BizCourseVideoLike;
import com.snail.service.BizCourseVideoLikeService;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class BizCourseVideoLikeServiceImpl extends ServiceImpl<BizCourseVideoLikeMapper, BizCourseVideoLike>
        implements BizCourseVideoLikeService {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    // Redis点赞集合Key
    private static final String LIKE_KEY = "course:video:like";
    // Redis取消点赞集合Key
    private static final String CANCEL_LIKE_KEY = "course:video:cancel:like";
    // 视频点赞数量统计Key
    private static final String LIKE_COUNT_KEY = "course:video:like:count:";

    @Override
    public void like(Long userId, Long courseVideoId) {
        // 生成唯一标识
        String likeKey = userId + ":" + courseVideoId;

        // 从取消点赞集合中移除(如果存在)
        redisTemplate.opsForSet().remove(CANCEL_LIKE_KEY, likeKey);
        // 添加到点赞集合
        Long addResult = redisTemplate.opsForSet().add(LIKE_KEY, likeKey);

        // 如果是新添加的点赞，增加点赞数
        if (addResult != null && addResult > 0) {
            redisTemplate.opsForValue().increment(LIKE_COUNT_KEY + courseVideoId);
        }
    }

    @Override
    public void cancelLike(Long userId, Long courseVideoId) {
        // 生成唯一标识
        String likeKey = userId + ":" + courseVideoId;

        // 从点赞集合中移除(如果存在)
        Long removeResult = redisTemplate.opsForSet().remove(LIKE_KEY, likeKey);
        // 添加到取消点赞集合
        redisTemplate.opsForSet().add(CANCEL_LIKE_KEY, likeKey);

        // 如果是真正移除的点赞，减少点赞数
        if (removeResult != null && removeResult > 0) {
            redisTemplate.opsForValue().decrement(LIKE_COUNT_KEY + courseVideoId);
        }
    }

    // 添加获取视频点赞数的方法
    @Override
    public Long getLikeCount(Long courseVideoId) {

        Object count = redisTemplate.opsForValue().get(LIKE_COUNT_KEY + courseVideoId);

        if (count == null) {
            // 如果Redis中没有，从数据库查询并同步到Redis
            LambdaQueryWrapper<BizCourseVideoLike> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BizCourseVideoLike::getCourseVideoId, courseVideoId)
                    .eq(BizCourseVideoLike::getDeleted, 0);
            long dbCount = count(queryWrapper);
            redisTemplate.opsForValue().set(LIKE_COUNT_KEY + courseVideoId, dbCount);
            return dbCount;
        }
        return Long.parseLong(count.toString());
    }

    /**
     * 定时任务：每5分钟同步一次数据到MySQL
     */
    @Scheduled(cron = "0 0/1 * * * ?")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void syncLikeToDb() {
        // 1. 处理点赞数据
        Set<Object> likeSet = redisTemplate.opsForSet().members(LIKE_KEY);
        if (likeSet != null && !likeSet.isEmpty()) {
            List<LikeDTO> likeList = likeSet.stream()
                    .map(obj -> {
                        String[] parts = obj.toString().split(":");
                        return new LikeDTO(Long.parseLong(parts[0]), Long.parseLong(parts[1]));
                    })
                    .collect(Collectors.toList());

            batchHandleLike(likeList);
            // 清空Redis中的点赞集合
            redisTemplate.delete(LIKE_KEY);
        }

        // 2. 处理取消点赞数据
        Set<Object> cancelSet = redisTemplate.opsForSet().members(CANCEL_LIKE_KEY);
        if (cancelSet != null && !cancelSet.isEmpty()) {
            List<LikeDTO> cancelList = cancelSet.stream()
                    .map(obj -> {
                        String[] parts = obj.toString().split(":");
                        return new LikeDTO(Long.parseLong(parts[0]), Long.parseLong(parts[1]));
                    })
                    .collect(Collectors.toList());

            batchHandleCancelLike(cancelList);
            // 清空Redis中的取消点赞集合
            redisTemplate.delete(CANCEL_LIKE_KEY);
        }
    }

    /**
     * 批量处理点赞
     */
    private void batchHandleLike(List<LikeDTO> likeList) {
        for (LikeDTO dto : likeList) {
            // 检查是否已经点赞
            LambdaQueryWrapper<BizCourseVideoLike> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BizCourseVideoLike::getUserId, dto.getUserId())
                    .eq(BizCourseVideoLike::getCourseVideoId, dto.getCourseVideoId());

            BizCourseVideoLike existLike = getOne(queryWrapper);

            if (existLike == null) {
                // 新增点赞记录
                BizCourseVideoLike like = new BizCourseVideoLike();
                like.setUserId(dto.getUserId());
                like.setCourseVideoId(dto.getCourseVideoId());
                like.setDeleted(0);
                like.setCreateTime(LocalDateTime.now());
                save(like);
            } else if (existLike.getDeleted() == 1) {
                // 重新点赞(更新状态)
                existLike.setDeleted(0);
                existLike.setDeletedTime(null);
                updateById(existLike);
            }
        }
    }

    /**
     * 批量处理取消点赞
     */
    private void batchHandleCancelLike(List<LikeDTO> cancelList) {
        for (LikeDTO dto : cancelList) {
            LambdaQueryWrapper<BizCourseVideoLike> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BizCourseVideoLike::getUserId, dto.getUserId())
                    .eq(BizCourseVideoLike::getCourseVideoId, dto.getCourseVideoId())
                    .eq(BizCourseVideoLike::getDeleted, 0);

            BizCourseVideoLike existLike = getOne(queryWrapper);

            if (existLike != null) {
                // 取消点赞
                existLike.setDeleted(1);
                existLike.setDeletedTime(LocalDateTime.now());
                updateById(existLike);
            }
        }
    }

    @Override
    public boolean hasLiked(Long userId, Long courseVideoId) {
        // 先检查Redis中是否有记录（优先从缓存查询）
        String likeKey = userId + ":" + courseVideoId;

        // 检查是否在点赞集合中
        Boolean isInLikeSet = redisTemplate.opsForSet().isMember(LIKE_KEY, likeKey);
        if (Boolean.TRUE.equals(isInLikeSet)) {
            return true;
        }

        // 检查是否在取消点赞集合中
        Boolean isInCancelSet = redisTemplate.opsForSet().isMember(CANCEL_LIKE_KEY, likeKey);
        if (Boolean.TRUE.equals(isInCancelSet)) {
            return false;
        }

        // Redis中没有记录，查询数据库
        LambdaQueryWrapper<BizCourseVideoLike> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BizCourseVideoLike::getUserId, userId)
                .eq(BizCourseVideoLike::getCourseVideoId, courseVideoId)
                .eq(BizCourseVideoLike::getDeleted, 0);

        return count(queryWrapper) > 0;
    }


}